using bookmeetingroom.Data;
using bookmeetingroom.Data.Entities;
using bookmeetingroom.Helper;
using bookmeetingroom.Services;
using bookmeetingroom.ViewModel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;


namespace bookmeetingroom.Controllers
{


    [Route("api/[controller]")]
    [ApiController]
    [Produces("application/json")]
    public class AccountController : ControllerBase
    {

        private readonly string REG_KEY = "__register__";
        private readonly string RESETPASSWORD_KEY = "__resetpassword__";

        private readonly string DEFAULT = "默认";

        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IEmailSender _emailSender;
        private readonly ILogger<AccountController> _logger;
        private readonly IWebHostEnvironment _hostingEnvironment;
        private readonly ApplicationDbContext _dbContext;

        private readonly IDistributedCache _distributedCache;
        public AccountController(UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager, IEmailSender emailSender,
            ILogger<AccountController> logger,
            IWebHostEnvironment hostingEnvironment,
            ApplicationDbContext dbContext,
            IDistributedCache distributedCache)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _logger = logger;
            _emailSender = emailSender;
            _hostingEnvironment = hostingEnvironment;
            _distributedCache = distributedCache;
            _dbContext = dbContext;
        }

        [HttpPost("SendValidationCode")]
        [AllowAnonymous]
        public IActionResult SendRegValidationCode([FromForm] string email)
        {
            var randomCode = GetID();

            string regkey = REG_KEY + email;

            _distributedCache.SetString(regkey, randomCode.ToString(), new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(5)));

            _emailSender.SendEmailRegister(email, email, randomCode.ToString(), _hostingEnvironment);

            _logger.LogInformation("注册验证码已发送。");

            var message = "验证码已发送到您的邮箱";

            return Ok(new { success = true, message });

        }

        /// <summary>
        /// 发送密码重置验证码，后台调用。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost("SendResetPasswordValidationCode")]
        [AllowAnonymous]
        public async Task<IActionResult> SendResetPasswordValidationCode([FromForm] string email)
        {

            var user = await _userManager.FindByEmailAsync(email);

            if (user == null) return Ok(new { success = false, message = "您尚未注册平台账号。" });

            var randomCode = GetID();

            string regkey = RESETPASSWORD_KEY + email;

            _distributedCache.SetString(regkey, randomCode.ToString(), new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(5)));

            _emailSender.SendEmailResetPassword(email, email, randomCode.ToString(), _hostingEnvironment);

            _logger.LogInformation("重设密码验证码已发送。");

            var message = "验证码已发送到您的邮箱";

            return Ok(new { success = true, message });
        }

        /// <summary>
        /// 获取一个随机的验证码
        /// </summary>
        /// <returns></returns>
        private int GetID()
        {
            return new Random().Next(100000, 999999); ;

        }

        [HttpPost("Register")]
        [AllowAnonymous]
        public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
        {
            if (!ModelState.IsValid)
            {
                string s = ModelState.GetErrorMessages();

                return BadRequest(s);

            }
            string key = REG_KEY + model.Email;

            var randomCode = _distributedCache.GetString(key);

            if (string.IsNullOrEmpty(randomCode))
            {
                return BadRequest("验证码已过期");
            }
            else if (randomCode != model.SecurityCode)
            {
                return BadRequest("验证码错误");
            }

            var user = await _userManager.FindByEmailAsync(model.Email);

            if (user != null) return BadRequest("邮箱已经被注册.");

            using var transaction = await _dbContext.Database.BeginTransactionAsync();
            try
            {
                Guid companyID = await CreateDefaultData(model.Email);

                user = new ApplicationUser
                {
                    Email = model.Email,
                    EmailConfirmed = true,
                    UserName = model.Email,
                    LockoutEnabled = true,
                    CompanyId = companyID,
                };
                var registerResult = await _userManager.CreateAsync(user, model.Password);

                if (!registerResult.Succeeded)
                {
                    string s = string.Join(" | ", registerResult.Errors.Select(n => n.Description));

                    return BadRequest(s);
                }

                await _userManager.AddToRoleAsync(user, "CustomerAdmin");

                await transaction.CommitAsync();

                var message = "注册成功";

                return Ok(new { success = true, message });
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();

                return Ok(new { success = true, message = ex.Message });
            }


        }
        private async Task<Guid> CreateDefaultData(string name)
        {
            //create a default company
            Company company = new Company
            {
                Name = DEFAULT,

                CreatedBy = name,
                UpdatedBy = name,
                CreatedTime = DateTime.Now,
                UpdatedTime = DateTime.Now
            };

            _dbContext.Add(company);

            await _dbContext.SaveChangesAsync();

            //create a default building
            Building building = new Building
            {
                Name = DEFAULT,
                CompanyId = company.Id,
                Default = true,
                CreatedBy = name,
                UpdatedBy = name,
                CreatedTime = DateTime.Now,
                UpdatedTime = DateTime.Now
            };


            _dbContext.Add(building);

            await _dbContext.SaveChangesAsync();
            return company.Id;


        }
        [HttpPost("ResetPassword")]
        [AllowAnonymous]
        public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                string s = ModelState.GetErrorMessages();

                return BadRequest(s);
            }

            string key = RESETPASSWORD_KEY + model.Email;

            var randomCode = _distributedCache.GetString(key);

            if (randomCode == null)
            {

                return BadRequest("验证码已过期");

            }
            else if (randomCode != model.SecurityCode)
            {

                return BadRequest("验证码错误");

            }
            else
            {
                var user = await _userManager.FindByEmailAsync(model.Email);

                if (user == null)
                {
                    // Don't reveal that the user does not exist
                    return BadRequest("邮箱不存在.");
                }
                var code = await _userManager.GeneratePasswordResetTokenAsync(user);

                var result = await _userManager.ResetPasswordAsync(user, code, model.Password);

                if (!result.Succeeded)
                {
                    string s = string.Join(" | ", result.Errors.Select(n => n.Description));

                    return BadRequest(s);
                }

            }
            var message = "重设密码成功";

            return Ok(new { success = true, message });
        }

        [HttpPost("UploadAvatar")]
        public async Task<IActionResult> UploadAvatar([FromServices] IWebHostEnvironment environment)
        {


            var files = Request.Form.Files;

            if (files == null || files.Count() <= 0)
            {

                return BadRequest("文件为空");

            }
            var file = files[0];


            if (file.Length == 0) return BadRequest("文件为空");

            string fileName = Path.GetFileNameWithoutExtension(file.FileName)
                + "_" + Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);

            string pysicalFileName = environment.WebRootPath + $@"/images/profile/{fileName}";

            using (FileStream fs = System.IO.File.Create(pysicalFileName))
            {
                await file.CopyToAsync(fs);

                await fs.FlushAsync();

            }

            return Ok(new { message = "", data = Request.Scheme + "://" + Request.Host.Value + "/images/profile/" + fileName });

        }
        [HttpPost("UpdateAvatar")]
        public async Task<IActionResult> UpdateAvatar([FromForm] string avatarurl)
        {
            var username = User.Identity.Name;

            var user = await _dbContext.Users.Where(n => n.UserName == username).FirstOrDefaultAsync();

            user.Avatar = avatarurl;

            if (user == null)
            {
                return NotFound("未找到此用户");
            }
            var result = await _userManager.UpdateAsync(user);

            var message = "头像更换成功";

            return Ok(new { success = true, message });
        }

        [HttpGet("UserProfile")]
        public async Task<IActionResult> UserProfile()
        {
            var user = await _dbContext.Users.Where(n => n.UserName == User.Identity.Name).FirstOrDefaultAsync();
            return Ok(new { success = true, Data = user });
        }

        [HttpPost("UpdateProfile")]
        public async Task<IActionResult> UpdateProfile(ApplicationUser profile)
        {

            var user = await _dbContext.Users.Where(n => n.UserName == User.Identity.Name).FirstOrDefaultAsync();


            user.Email = profile.Email;
            user.BirthDate = profile.BirthDate.Date;
            user.Hobbies = profile.Hobbies;
            user.Gender = profile.Gender;
            user.PhoneNumber = profile.PhoneNumber;


            await _userManager.UpdateAsync(user);

            return Ok(new { success = true, Message = "个人信息更新成功" });

        }

    }
}